home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / gfx / misc / dctvdev3.lzh / example / graygrad.c < prev   
C/C++ Source or Header  |  1992-08-12  |  16KB  |  511 lines

  1. /**********************************************************************
  2. *
  3. *   graygrad.c - Convert DCTV gradient to 4-bit gray screen.
  4. *
  5. *   Copyright (C) 1992 Digital Creations, Inc.
  6. *
  7. *   DESCRIPTION
  8. *       This example demonstrates how to call dctv.library to convert
  9. *       a DCTV display BitMap to 24-bit RGB.  The source DCTV BitMap
  10. *       is a gradient generated in the same manner as in dctvgrad.c.
  11. *       This DCTV image is then converted line by line to 24-bit RGB.
  12. *       Then the upper 4 bits of the blue component are displayed on
  13. *       a 16-color hires screen.
  14. *
  15. *       (not particularly flashy, but at least you get to see something).
  16. *
  17. *       Program runs under Amiga OS v1.3 and higher.
  18. *
  19. *   USAGE
  20. *       graygrad <width> <height> <depth>
  21. *           width  - screen width (640..736)
  22. *           height - screen height (200..241, 400..482)
  23. *           depth  - screen depth (3..4)
  24. *
  25. *       Terminate with Control+C.
  26. *
  27. *   COMPILATION
  28. *       SAS/C:      (v5.10 or higher.  Regular of ANSI libs)
  29. *           lc -L+dctv.lib graygrad
  30. *
  31. *       Aztec C:    (v5.0a or higher)
  32. *           cc graygrad [works w/ either 16 or 32 bit int's]
  33. *           ln graygrad.o +l dctv.lib -lc
  34. *
  35. *   REQUIREMENTS
  36. *       . Aztec C 5.0 or SAS/C 5.10.
  37. *       . v37.4 or higher Amiga include files.
  38. *       . OS #pragmas created for your compiler in the pragmas
  39. *         directory of your include path.
  40. *
  41. **********************************************************************/
  42.  
  43. #include <dos/dos.h>
  44. #include <exec/memory.h>
  45. #include <intuition/screens.h>
  46. #include <libraries/dctv.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50.  
  51. #include <clib/dctv_protos.h>
  52. #include <clib/exec_protos.h>
  53. #include <clib/graphics_protos.h>
  54. #include <clib/intuition_protos.h>
  55.  
  56. #include <pragmas/dctv_pragmas.h>
  57. #include <pragmas/exec_pragmas.h>
  58. #include <pragmas/graphics_pragmas.h>
  59. #include <pragmas/intuition_pragmas.h>
  60.  
  61.  
  62. /* -------------------- misc defines */
  63.  
  64. #define DCTVLIB_Version 3
  65. #define READPIXEL 0         /* selects DCTV->RGB conversion method: set to 1 to use ReadDCTVPixel(), 0 to use CvtDCTVLine() */
  66.  
  67. #define LaceHeight(height) (height > 350)
  68.  
  69.  
  70. /* -------------------- data */
  71.  
  72. struct Library *DCTVBase, *GfxBase, *IntuitionBase;
  73.  
  74.  
  75. /* -------------------- local functions */
  76.  
  77. void dograd (short width, short height, short depth);
  78. BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height);
  79. void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height);
  80.  
  81.     /* bitmap allocator */
  82. struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth);
  83. void freebm (struct BitMap *);
  84.  
  85.     /* gradient functions */
  86. void initgrad (struct DCTVCvtHandle *);
  87. void rendergradline (struct DCTVCvtHandle *);
  88.  
  89.  
  90. /* -------------------- main() */
  91.  
  92. #if AZTEC_C
  93.   void _wb_parse (void) {}      /* stub out wb window parser */
  94. #endif
  95.  
  96. #if __SASC  /* suppress normal Ctrl-C processing (SAS/C) */
  97.   void __chkabort (void) {}
  98.   void chkabort (void) {}
  99. #endif
  100.  
  101. int main (int argc, char **argv)
  102. {
  103.     if (argc < 4) goto clean;
  104.  
  105.   #if AZTEC_C           /* suppress normal Ctrl-C processing (Aztec C) */
  106.     {
  107.         extern int Enable_Abort;
  108.         Enable_Abort = 0;
  109.     }
  110.   #endif
  111.  
  112.     if (!(IntuitionBase = OpenLibrary ("intuition.library", LIBRARY_MINIMUM))) goto clean;
  113.     if (!(GfxBase = OpenLibrary ("graphics.library", LIBRARY_MINIMUM))) goto clean;
  114.     if (!(DCTVBase = OpenLibrary ("dctv.library", DCTVLIB_Version))) {
  115.         printf ("requires dctv.library v%d\n", DCTVLIB_Version);
  116.         goto clean;
  117.     }
  118.  
  119.     dograd (atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
  120.  
  121. clean:
  122.     if (DCTVBase) CloseLibrary (DCTVBase);
  123.     if (GfxBase) CloseLibrary (GfxBase);
  124.     if (IntuitionBase) CloseLibrary (IntuitionBase);
  125.     return 0;
  126. }
  127.  
  128.  
  129. /* -------------------- dograd() */
  130.  
  131. void dograd (short width, short height, short depth)
  132. {
  133.     struct BitMap *dctvbm = NULL;
  134.     UWORD *palette = NULL;
  135.  
  136.         /* pad width to next multiple of 16 */
  137.     width = width + 15 & ~15;
  138.  
  139.         /* allocate a bitmap and palette to hold DCTV display image.
  140.            Notice that this BitMap is not allocated in chip ram as the
  141.            conversions don't require the bitmap to be displayable. */
  142.     if (!(dctvbm = allocbm (width, height, depth)) ||
  143.         !(palette = AllocMem (sizeof (UWORD) << depth, MEMF_ANY | MEMF_CLEAR))) {
  144.         puts ("Out of memory\n");
  145.         goto clean;
  146.     }
  147.  
  148.         /* build DCTV bitmap (draw same gradient as dctvgrad.c) */
  149.     if (!makedctvbm (dctvbm, palette, width, height)) goto clean;
  150.  
  151.         /* convert DCTV display image to a 16-color gray screen of the
  152.            same size as the BitMap */
  153.     showgrad (dctvbm, palette, width, height);
  154.  
  155. clean:
  156.     if (palette) FreeMem (palette, sizeof (UWORD) << depth);
  157.     if (dctvbm) freebm (dctvbm);
  158. }
  159.  
  160.  
  161. /* -------------------- DCTV gradient bitmap builder */
  162.  
  163. /* this part is pretty much the same as in dctvgrad.c */
  164.  
  165. BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height)
  166. {
  167.     struct DCTVCvtHandle *cvt = NULL;
  168.     ULONG errcode;
  169.     BOOL rtn = FALSE;
  170.  
  171.     puts ("Making gradient.");
  172.  
  173.         /* Allocate DCTV conversion environment. */
  174.     if (!(cvt = AllocDCTVCvtTags ( dctvbm,
  175.                                    DCTVCVTA_Type,       (ULONG)DCTVCVTT_RGBtoDCTV,
  176.                                    DCTVCVTA_Width,      (ULONG)width,
  177.                                    DCTVCVTA_Height,     (ULONG)height,
  178.                                    DCTVCVTA_Flags,      (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
  179.                                    DCTVCVTA_ErrorCode,  &errcode,
  180.                                    TAG_END ))) {
  181.  
  182.         printf ("AllocDCTVCvtTags failed %lu\n", errcode);
  183.         goto clean;
  184.     }
  185.  
  186.         /* copy ColorTable to palette */
  187.     CopyMem (cvt->ColorTable, palette, cvt->NColors * sizeof (UWORD));
  188.  
  189.         /* initialize gradient */
  190.     initgrad (cvt);                 /* Init gradient data. */
  191.  
  192.         /* Line rendering loop.  (See dctvgrad.c for a more complete explanation of this) */
  193.     while (cvt->DstLineNum < cvt->Height) {
  194.  
  195.                                     /* Abort on Ctrl-C. */
  196.         if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto clean;
  197.  
  198.         rendergradline (cvt);       /* Render a line of the gradient to
  199.                                        DCTVCvtHandle RGB line buffer.
  200.                                        This function is smart enough to
  201.                                        handle line #'s out of range. */
  202.  
  203.         CvtDCTVLine (cvt);          /* Convert the line in the line buffer to
  204.                                        DCTV display data. Results in rendering
  205.                                        a line of the BitMap. */
  206.     }
  207.  
  208.     rtn = TRUE;
  209.  
  210. clean:
  211.     if (cvt) FreeDCTVCvt (cvt);
  212.     return rtn;
  213. }
  214.  
  215.  
  216. /* -------------------- gray gradient display */
  217.  
  218. struct Screen *openscreen (short width, short height);
  219. BOOL rendergrayscreen (struct Screen *, struct DCTVCvtHandle *);
  220.  
  221. void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height)
  222. {
  223.     struct Screen *screen = NULL;
  224.     struct DCTVCvtHandle *cvt = NULL;
  225.     ULONG errcode;
  226.  
  227.     puts ("Building Screen.");
  228.  
  229.     if (!(screen = openscreen (width, height))) {
  230.         puts ("openscreen() failed\n");
  231.         goto clean;
  232.     }
  233.  
  234.     if (!(cvt = AllocDCTVCvtTags ( dctvbm,
  235.                                    DCTVCVTA_Type,       (ULONG)DCTVCVTT_DCTVtoRGB,
  236.                                    DCTVCVTA_Width,      (ULONG)width,
  237.                                    DCTVCVTA_Height,     (ULONG)height,
  238.                                    DCTVCVTA_Flags,      (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
  239.                                    DCTVCVTA_ColorTable, palette,
  240.                                    DCTVCVTA_ErrorCode,  &errcode,
  241.                                    TAG_END ))) {
  242.  
  243.         printf ("AllocDCTVCvtTags() failed %lu\n", errcode);
  244.         goto clean;
  245.     }
  246.  
  247.     if (!rendergrayscreen (screen, cvt)) goto clean;
  248.  
  249.     puts ("Press Ctrl-C");
  250.     Wait (SIGBREAKF_CTRL_C);
  251.  
  252. clean:
  253.     if (cvt) FreeDCTVCvt (cvt);
  254.     if (screen) CloseScreen (screen);
  255. }
  256.  
  257. struct Screen *openscreen (short width, short height)
  258. {
  259.     static struct NewScreen newscreen = {
  260.         0, 0, 0, 0, 4,
  261.         -1, -1,
  262.         0,
  263.         CUSTOMSCREEN | SCREENQUIET,
  264.         NULL,
  265.         "graygrad",
  266.         NULL,
  267.         NULL
  268.     };
  269.     static UWORD palette[] = {          /* gray palette */
  270.         0x000, 0x111, 0x222, 0x333,
  271.         0x444, 0x555, 0x666, 0x777,
  272.         0x888, 0x999, 0xaaa, 0xbbb,
  273.         0xccc, 0xddd, 0xeee, 0xfff
  274.     };
  275.     struct Screen *screen;
  276.  
  277.     newscreen.Width = width;
  278.     newscreen.Height = height;
  279.     newscreen.ViewModes = LaceHeight(height) ? HIRESLACE_KEY : HIRES_KEY;
  280.  
  281.     if (screen = OpenScreen (&newscreen)) {
  282.         LoadRGB4 (&screen->ViewPort, palette, 16);
  283.     }
  284.  
  285.     return screen;
  286. }
  287.  
  288. #if READPIXEL
  289.  
  290. /* display gradient using ReadDCTVPixel() */
  291.  
  292. BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
  293. {
  294.     struct RastPort *rp = &screen->RastPort;
  295.     short x, y;
  296.  
  297.     /* !!! fix docs! */
  298.         /*
  299.             Line rendering loop.
  300.  
  301.             Loop until all Destination lines have been converted
  302.             (indicated by DstLineNum >= height).
  303.  
  304.             Because the conversion process may introduce an N-line delay
  305.             between source and destination lines, you must call
  306.             CvtDCTVLine() until all the destination lines have been
  307.             converted.  That means the code in this loop will be
  308.             executed (height + NDelayLines) times.
  309.  
  310.             Your rendering RGB processing code should use DstLineNum-1
  311.             after converting each line to figure out which RGB line was
  312.             just made.
  313.  
  314.             Since the range of DstLineNum is
  315.             -NDelayLines < DstLineNum <= Height after each call, you need
  316.             to make sure that CvtDCTVLine() actually output a line for you
  317.             to use.  If DstLineNum is in the range of
  318.             0 < DstLineNum <= Height after calling CvtDCTVLine() then a
  319.             line of RGB was just emitted.
  320.         */
  321.  
  322.     /*
  323.         Convert the current line in the RGB line buffer to 4-bit gray by
  324.         extracting just the upper 4 bits of the Blue component.
  325.  
  326.         The caller of this function is expected to avoid calling it for
  327.         DstLineNum values out of range.
  328.  
  329.         The line being displayed is DstLineNum-1 (DstLineNum indicates the
  330.         _next_ line to be output by CvtDCTVLine()).
  331.  
  332.         NOTE: this loop is pathetically slow (mainly due to WritePixel()),
  333.         but is sufficient for this example.
  334.     */
  335.  
  336.     SetDrMd (rp, JAM1);
  337.  
  338.     for (x = 0; x < screen->Width; x++) {
  339.                                     /* Abort on Ctrl-C. */
  340.         if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
  341.  
  342.         for (y = 0; y < screen->Height; y++) {
  343.             SetAPen (rp, (ReadDCTVPixel (cvt, x, y) & 0xf0) >> 4);      /* get upper 4 bits of blue */
  344.             WritePixel (rp, x, y);
  345.         }
  346.     }
  347.  
  348.     return TRUE;
  349. }
  350.  
  351. #else
  352.  
  353. /* display gradient using CvtDCTVLine() */
  354.  
  355. void rendergrayline (struct RastPort *, struct DCTVCvtHandle *);
  356.  
  357. BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
  358. {
  359.         /*
  360.             Line rendering loop.
  361.  
  362.             Loop until all Destination lines have been converted
  363.             (indicated by DstLineNum >= height).
  364.  
  365.             Because the conversion process may introduce an N-line delay
  366.             between source and destination lines, you must call
  367.             CvtDCTVLine() until all the destination lines have been
  368.             converted.  That means the code in this loop will be
  369.             executed (height + NDelayLines) times.
  370.  
  371.             Your rendering RGB processing code should use DstLineNum-1
  372.             after converting each line to figure out which RGB line was
  373.             just made.
  374.  
  375.             Since the range of DstLineNum is
  376.             -NDelayLines < DstLineNum <= Height after each call, you need
  377.             to make sure that CvtDCTVLine() actually output a line for you
  378.             to use.  If DstLineNum is in the range of
  379.             0 < DstLineNum <= Height after calling CvtDCTVLine() then a
  380.             line of RGB was just emitted.
  381.         */
  382.  
  383.     while (cvt->DstLineNum < cvt->Height) {
  384.  
  385.                                     /* Abort on Ctrl-C. */
  386.         if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
  387.  
  388.         CvtDCTVLine (cvt);          /* Convert the line in the line buffer to
  389.                                        DCTV display data. Results in rendering
  390.                                        a line of the BitMap. */
  391.  
  392.                                     /* Display 4-bit gray from 24-bit RGB.
  393.                                        This draws directly to the Screen's Rastport. */
  394.         if (cvt->DstLineNum > 0)
  395.             rendergrayline (&screen->RastPort, cvt);
  396.     }
  397.  
  398.     return TRUE;
  399. }
  400.  
  401. void rendergrayline (struct RastPort *rp, struct DCTVCvtHandle *cvt)
  402. {
  403.     short x;
  404.     short y = cvt->DstLineNum - 1;      /* after call, subtract 1 for line just emitted */
  405.  
  406.     /*
  407.         Convert the current line in the RGB line buffer to 4-bit gray by
  408.         extracting just the upper 4 bits of the Blue component.
  409.  
  410.         The caller of this function is expected to avoid calling it for
  411.         DstLineNum values out of range.
  412.  
  413.         The line being displayed is DstLineNum-1 (DstLineNum indicates the
  414.         _next_ line to be output by CvtDCTVLine()).
  415.  
  416.         NOTE: this loop is pathetically slow (mainly due to WritePixel()),
  417.         but is sufficient for this example.
  418.     */
  419.  
  420.     SetDrMd (rp, JAM1);
  421.  
  422.     for (x = 0; x < cvt->Width; x++) {
  423.         SetAPen (rp, cvt->Blue[x] >> 4);
  424.         WritePixel (rp, x, y);
  425.     }
  426. }
  427.  
  428. #endif
  429.  
  430.  
  431. /* -------------------- bitmap allocator */
  432.  
  433. struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth)
  434. {
  435.     ULONG memsize;
  436.     PLANEPTR *ras;
  437.     struct BitMap *bm;
  438.  
  439.     if (depth > 8) goto clean;
  440.  
  441.     if (!(bm = AllocMem (sizeof *bm, MEMF_ANY | MEMF_CLEAR))) goto clean;
  442.     InitBitMap (bm, depth, width, height);
  443.  
  444.     memsize = (ULONG)bm->Rows * bm->BytesPerRow;
  445.     for (ras=bm->Planes; depth--;) {
  446.         if (!(*ras++ = AllocMem (memsize, MEMF_ANY | MEMF_CLEAR))) goto clean;
  447.     }
  448.  
  449.     return bm;
  450.  
  451. clean:
  452.     if (bm) freebm (bm);
  453.     return NULL;
  454. }
  455.  
  456. void freebm (struct BitMap *bm)
  457. {
  458.     ULONG rassize = (ULONG)bm->Rows * bm->BytesPerRow;
  459.     PLANEPTR *ras;
  460.     short i;
  461.  
  462.     for (ras = bm->Planes, i = bm->Depth; i--; ras++) {
  463.         if (*ras) {
  464.             FreeMem (*ras, rassize);
  465.             *ras = NULL;
  466.         }
  467.     }
  468.     FreeMem (bm, sizeof *bm);
  469. }
  470.  
  471.  
  472. /* -------------------- 24-bit RGB gradient functions */
  473.  
  474. #define gcent(m,l)  (((m)-(l)) / 2)         /* centering macro */
  475.  
  476. void initgrad (struct DCTVCvtHandle *cvt)
  477. {
  478.     short bufwidth   = cvt->Width;
  479.     short imagewidth = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
  480.     short i;
  481.  
  482.         /* init line to black */
  483.     memset (cvt->Red, 0, bufwidth);
  484.     memset (cvt->Green, 0, bufwidth);
  485.     memset (cvt->Blue, 0, bufwidth);
  486.  
  487.         /* ramp red horizontally */
  488.     for (i=0; i < imagewidth; i++)
  489.         cvt->Red [i+cvt->ImageBounds.MinX] = (ULONG)i * 255 / imagewidth;
  490. }
  491.  
  492. void rendergradline (struct DCTVCvtHandle *cvt)
  493. {
  494.     short imagewidth  = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
  495.     short imageheight = cvt->ImageBounds.MaxY - cvt->ImageBounds.MinY + 1;
  496.     short y = cvt->SrcLineNum - cvt->ImageBounds.MinY;
  497.     short bluewidth;
  498.     UBYTE greenval;
  499.  
  500.     if (y >= 0 && y < imageheight) {
  501.             /* constant green component for line */
  502.         greenval = (long)y * 255 / imageheight;
  503.         memset (cvt->Green + cvt->ImageBounds.MinX, greenval, imagewidth);
  504.  
  505.             /* reverse wedge blue component */
  506.         bluewidth = (long)(imageheight - y) * imagewidth / imageheight;
  507.         if (bluewidth > 0)
  508.             memset (cvt->Blue + gcent (imagewidth, bluewidth) + cvt->ImageBounds.MinX, 255-greenval, bluewidth);
  509.     }
  510. }
  511.